/**
* @author ishaikh
*
*/
package com.transformuk.bdt.view;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.view.AbstractView;
import com.itextpdf.text.Anchor;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chunk;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.Font.FontFamily;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.ColumnText;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfPageEventHelper;
import com.itextpdf.text.pdf.PdfWriter;
import com.itextpdf.tool.xml.Pipeline;
import com.itextpdf.tool.xml.XMLWorker;
import com.itextpdf.tool.xml.XMLWorkerHelper;
import com.itextpdf.tool.xml.html.Tags;
import com.itextpdf.tool.xml.parser.XMLParser;
import com.itextpdf.tool.xml.pipeline.css.CSSResolver;
import com.itextpdf.tool.xml.pipeline.css.CssResolverPipeline;
import com.itextpdf.tool.xml.pipeline.end.PdfWriterPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipeline;
import com.itextpdf.tool.xml.pipeline.html.HtmlPipelineContext;
import com.transformuk.bdt.domain.Bfsf;
import com.transformuk.bdt.model.OtherSources;
import com.transformuk.bdt.model.ReportModel;
import com.transformuk.bdt.tld.Utils;
@Component
public class PdfReportView extends AbstractView {
private static final int THREE = 3;
private static final Logger logger = Logger.getLogger(PdfReportView.class);
/** The fonts */
public static final Font[] FONT = new Font[7];
static {
FONT[0] = new Font(FontFamily.HELVETICA, 24);
FONT[1] = new Font(FontFamily.HELVETICA, 18, Font.BOLD);
FONT[2] = new Font(FontFamily.HELVETICA, 12, Font.BOLD);
FONT[3] = new Font(FontFamily.HELVETICA, 12);
FONT[4] = new Font(FontFamily.HELVETICA, 12, Font.UNDERLINE, new BaseColor(0, 0, 255));
FONT[5] = new Font(FontFamily.HELVETICA, 14, Font.BOLD);
FONT[6] = new Font(FontFamily.HELVETICA, 10);
}
public PdfReportView() {
setContentType("application/pdf");
}
@Override
protected boolean generatesDownloadContent() {
return true;
}
@Override
protected void renderMergedOutputModel(Map<String, Object> model,
HttpServletRequest req, HttpServletResponse res) throws Exception {
String ROOT_PATH = System.getProperty("catalina.home");
// get data model which is passed by the Spring container
ReportModel reportModel = (ReportModel) model.get("reportModel");
// IE workaround: write into byte array first.
ByteArrayOutputStream baos = createTemporaryOutputStream();
// step 1
Document document = new Document(PageSize.A4, 30, 30, 30, 40);
// step 2
PdfWriter writer = newWriter(document, baos);//PdfWriter.getInstance(document, new FileOutputStream(ROOT_PATH + File.separator +"pdf.pdf"));
writer.setBoxSize("art", new Rectangle(36, 54, 559, 788));
writer.setPageEvent(new HeaderFooter());
writer.setViewerPreferences(getViewerPreferences());
// step 3
document.open();
document.add(new Chunk(""));
// step 4
try {
HtmlPipelineContext htmlContext = new HtmlPipelineContext(null);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
CSSResolver cssResolver = XMLWorkerHelper.getInstance()
.getDefaultCssResolver(true);
Pipeline<?> pipeline = new CssResolverPipeline(cssResolver,
new HtmlPipeline(htmlContext, new PdfWriterPipeline(document,
writer)));
XMLWorker worker = new XMLWorker(pipeline, true);
XMLParser p = new XMLParser(worker);
p.parse(new InputStreamReader(new FileInputStream(ROOT_PATH + File.separator + "bis.html"), "UTF-8"));
//add mysupport
addIntroAndMySupport(document);
//add support and other information
addSupportAndOtherInformation(document, reportModel);
//add other useful sources
addOtherUsefulSources(document);
//add user data
addUserData(document, reportModel);
//add footer
addFooterSection(document);
}catch(Exception e) {
logger.error("Exception creating pdf: "+e.getMessage());
}
//step 5
document.close();
// Flush to HTTP response.
writeToResponse(res, baos);
}
private int getViewerPreferences() {
return PdfWriter.ALLOW_PRINTING | PdfWriter.PageLayoutSinglePage;
}
private PdfWriter newWriter(Document document, OutputStream os) throws DocumentException {
return PdfWriter.getInstance(document, os);
}
public static void addIntroAndMySupport(Document document) throws DocumentException {
//add line feed
document.add(new Paragraph(" "));
Paragraph paragraph = new Paragraph("The national and local links below have been chosen as the " +
"most relevant sources of help and support for your business needs.", FONT[3]);
document.add(paragraph);
//add line feed
document.add(new Paragraph(" "));
paragraph = new Paragraph("My support", FONT[1]);
document.add(paragraph);
paragraph = new Paragraph("Links to support sources are listed in the areas you have indicated are important to you. " +
"Some are related to your stated needs, and others are based on possible needs we have interpreted from your answers.", FONT[2]);
document.add(paragraph);
}
public static void addSupportAndOtherInformation(Document document, ReportModel reportModel) throws DocumentException {
Map<String, List<Bfsf>> bfsfSearchResultMap = reportModel.getSearchResult();
Map<String, List<OtherSources>> otherSourcesMap = reportModel.getOtherSources();
if (bfsfSearchResultMap != null || otherSourcesMap != null) {
for (Entry<String, List<Bfsf>> entry : bfsfSearchResultMap.entrySet()) {
//add line feed
document.add(new Paragraph(" "));
Paragraph paragraph = new Paragraph(entry.getKey(), FONT[1]);
document.add(paragraph);
//add line feed
document.add(new Paragraph(" "));
paragraph = new Paragraph("Support", FONT[5]);
document.add(paragraph);
for (Bfsf bfsf : entry.getValue()) {
Phrase p = new Phrase();
Anchor anchor = new Anchor(bfsf.getTitle() + " » ", FONT[4]);
anchor.setReference(bfsf.getWeb_url());
p.add(anchor);
p.add(new Chunk(bfsf.getShort_description(), FONT[3]));
document.add(p);
//add line feed
document.add(new Paragraph(" "));
}
if (otherSourcesMap != null) {
List<OtherSources> otherSourcesList = otherSourcesMap.get(entry.getKey());
paragraph = new Paragraph("Other information", FONT[5]);
document.add(paragraph);
int recordCount = 0;
for (OtherSources otherSources : otherSourcesList) {
//only show first three records
if (recordCount < THREE) {
Phrase p = new Phrase();
Anchor anchor = new Anchor(Utils.stripHtml(otherSources.getTitle()) + " » ", FONT[4]);
anchor.setReference(otherSources.getUrl());
p.add(anchor);
String description = "";
if (StringUtils.isNotBlank(otherSources.getDescription())) {
description = Utils.stripHtml(otherSources.getDescription());
} else {
String content = StringUtils.substringAfter(otherSources.getContent(), "<LABEL>Search</LABEL> <A>Home</A> <A>Business and self-employed</A>");
description = Utils.abbreviate(Utils.stripHtml(content), 143);
}
p.add(new Chunk(description, FONT[3]));
document.add(p);
//add line feed
document.add(new Paragraph(" "));
recordCount++;
}
}
}
}
}
}
public static void addUserData(Document document, ReportModel reportModel) throws DocumentException {
//add line feed
document.add(new Paragraph(" "));
Paragraph paragraph = new Paragraph("My business", FONT[1]);
document.add(paragraph);
//add line feed
document.add(new Paragraph(" "));
// a table with three columns
PdfPTable table = new PdfPTable(2);
table.setHorizontalAlignment(Element.ALIGN_LEFT);
table.setWidthPercentage(50);
table.setSpacingBefore(5);
// we add a cell with colspan 2
PdfPCell cell = new PdfPCell(new Phrase("Information provided", FONT[2]));
cell.setColspan(2);
//cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
//cell.setGrayFill(0.9f);
cell.setHorizontalAlignment(Element.ALIGN_RIGHT);
cell.setPadding(5);
table.addCell(cell);
if (StringUtils.isNotBlank(reportModel.getBusinessAge())) {
table.addCell("Business age");
table.addCell(new PdfPCell(new Phrase(reportModel.getBusinessAge(), FONT[6])));
}
if (StringUtils.isNotBlank(reportModel.getLegalStructure())) {
table.addCell("Legal structure");
table.addCell(new PdfPCell(new Phrase(reportModel.getLegalStructure(), FONT[6])));
}
if (StringUtils.isNotBlank(reportModel.getPostCode())) {
table.addCell("Location");
table.addCell(new PdfPCell(new Phrase(reportModel.getPostCode(), FONT[6])));
}
if (StringUtils.isNotBlank(reportModel.getWorkforce())) {
table.addCell("Workforce");
table.addCell(new PdfPCell(new Phrase(reportModel.getWorkforce(), FONT[6])));
}
if (StringUtils.isNotBlank(reportModel.getSector())) {
table.addCell("Sector");
table.addCell(new PdfPCell(new Phrase(reportModel.getSector(), FONT[6])));
}
document.add(table);
}
private void addOtherUsefulSources(Document document) throws DocumentException {
//add line feed
//document.add(new Paragraph(" "));
Paragraph paragraph = new Paragraph("Other useful sources:", FONT[1]);
document.add(paragraph);
Phrase p = new Phrase();
p.add(new Chunk("For support, Advice and inspiration for growing your business, visit ", FONT[3]));
Anchor anchor = new Anchor("GREATBusiness »", FONT[4]);
anchor.setReference("http://www.greatbusiness.gov.uk");
p.add(anchor);
document.add(p);
//add line feed
document.add(new Paragraph(" "));
document.add(new Paragraph("You may also find these schemes and organisations useful:", FONT[3]));
//add line feed
document.add(new Paragraph(" "));
paragraph = new Paragraph();
anchor = new Anchor("Growth Vouchers »", FONT[4]);
anchor.setReference("https://marketplace.enterprisenation.com/about");
paragraph.add(anchor);
document.add(paragraph);
document.add(new Paragraph("Accessing strategic business advice. Find out how Growth Vouchers can help your business to grow.", FONT[3]));
//add line feed
document.add(new Paragraph(" "));
paragraph = new Paragraph();
anchor = new Anchor("British Business Bank »", FONT[4]);
anchor.setReference("http://british-business-bank.co.uk/");
paragraph.add(anchor);
document.add(paragraph);
p = new Phrase();
p.add(new Chunk("Unlocking finance. Find out how the British Business Bank is making financial markets work for smaller businesses; or see their guide to finance sources and tools - ", FONT[3]));
anchor = new Anchor("The Business Finance Guide »", FONT[4]);
anchor.setReference("http://www.icaew.com/~/media/Files/Technical/Corporate-finance/Guidelines/the-business-finance-guide.pdf");
p.add(anchor);
document.add(p);
//add line feed
document.add(new Paragraph(" "));
paragraph = new Paragraph();
anchor = new Anchor("Innovate UK »", FONT[4]);
anchor.setReference("http://www.innovateuk.org/");
paragraph.add(anchor);
document.add(paragraph);
document.add(new Paragraph("If you're looking to develop new products and services and bring them closer to market, Innovate UK provides a range of funding programmes and support.", FONT[3]));
//add line feed
document.add(new Paragraph(" "));
paragraph = new Paragraph();
anchor = new Anchor("Apprenticeships »", FONT[4]);
anchor.setReference("http://www.greatbusiness.gov.uk/apprenticeships/");
paragraph.add(anchor);
document.add(paragraph);
document.add(new Paragraph("Apprenticeships are great for employers - apprentices improve productivity and help give businesses a competitive edge.", FONT[3]));
//add line feed
document.add(new Paragraph(" "));
paragraph = new Paragraph();
anchor = new Anchor("Contracts Finder »", FONT[4]);
anchor.setReference("https://www.gov.uk/contracts-finder");
paragraph.add(anchor);
document.add(paragraph);
document.add(new Paragraph("Contracts Finder lets you search for information about contracts worth over £10,000 with the government and its agencies.", FONT[3]));
}
private void addFooterSection(Document document) throws DocumentException {
//add line feed
document.add(new Paragraph(" "));
Paragraph paragraph = new Paragraph("Want to speak to someone?", FONT[1]);
document.add(paragraph);
document.add(new Phrase("You can call the national Business Support Helpline on 0300 456 3565 (Monday to Friday, 9am – 6pm).", FONT[3]));
//add line feed
document.add(new Paragraph(" "));
Phrase p = new Phrase();
p.add(new Chunk("You can also talk to a local business adviser at ", FONT[3]));
Anchor anchor = new Anchor("Greater London Authority", FONT[4]);
anchor.setReference("https://www.london.gov.uk/priorities/business-economy/for-business/business-support");
p.add(anchor);
p.add(new Chunk(" on 0300 456 3565.", FONT[3]));
document.add(p);
//add line feed
document.add(new Paragraph(" "));
Paragraph para = new Paragraph();
anchor = new Anchor("Find out about call charges »", FONT[4]);
anchor.setReference("https://www.gov.uk/call-charges");
para.add(anchor);
document.add(para);
}
/** Inner class to add a header and a footer. */
class HeaderFooter extends PdfPageEventHelper {
/** Current page number (will be reset for every chapter). */
int pagenumber;
/**
* Increase the page number.
* @see com.itextpdf.text.pdf.PdfPageEventHelper#onStartPage(
* com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
*/
public void onStartPage(PdfWriter writer, Document document) {
pagenumber++;
}
/**
* Adds the header and the footer.
* @see com.itextpdf.text.pdf.PdfPageEventHelper#onEndPage(
* com.itextpdf.text.pdf.PdfWriter, com.itextpdf.text.Document)
*/
public void onEndPage(PdfWriter writer, Document document) {
Rectangle rect = writer.getBoxSize("art");
ColumnText.showTextAligned(writer.getDirectContent(),
Element.ALIGN_CENTER, new Phrase(String.format("page %d", pagenumber)),
(rect.getLeft() + rect.getRight()) / 2, rect.getBottom() - 18, 0);
}
}
}